home *** CD-ROM | disk | FTP | other *** search
/ Complete Linux / Complete Linux.iso / docs / apps / database / postgres / postgre4.z / postgre4 / src / utils / cache / inval.c < prev    next >
Encoding:
C/C++ Source or Header  |  1992-08-27  |  16.2 KB  |  625 lines

  1. /* ----------------------------------------------------------------
  2.  * inval.c --
  3.  *    POSTGRES cache invalidation dispatcher code.
  4.  *
  5.  * Note - this code is real crufty...
  6.  * ----------------------------------------------------------------
  7.  */
  8. #include "tmp/postgres.h"
  9. #include "access/heapam.h"    /* XXX to support hacks below */
  10. #include "access/htup.h"
  11. #include "storage/bufpage.h"
  12. #include "storage/buf.h"    /* XXX for InvalidBuffer */
  13. #include "storage/ipci.h"
  14. #include "storage/sinval.h"
  15. #include "utils/catcache.h"
  16. #include "utils/linval.h"
  17. #include "utils/inval.h"
  18. #include "utils/log.h"
  19. #include "utils/rel.h"
  20. #include "catalog/catname.h"    /* XXX to support hacks below */
  21. #include "catalog/syscache.h"    /* XXX to support the hacks below */
  22.  
  23. RcsId("$Header: /private/postgres/src/utils/cache/RCS/inval.c,v 1.12 1992/08/24 22:25:53 mao Exp $");
  24.  
  25. /* ----------------
  26.  *    private invalidation structures
  27.  * ----------------
  28.  */
  29. typedef struct CatalogInvalidationData {
  30.     Index        cacheId;
  31.     Index        hashIndex;
  32.     ItemPointerData    pointerData;
  33. } CatalogInvalidationData;
  34.  
  35. typedef struct RelationInvalidationData {
  36.     ObjectId    relationId;
  37.     ObjectId    objectId;
  38. } RelationInvalidationData;
  39.  
  40. typedef union AnyInvalidation {
  41.     CatalogInvalidationData        catalog;
  42.     RelationInvalidationData    relation;
  43. } AnyInvalidation;
  44.  
  45. typedef struct InvalidationMessageData {
  46.     char        kind;
  47.     AnyInvalidation    any;
  48. } InvalidationMessageData;
  49.  
  50. typedef InvalidationMessageData    *InvalidationMessage;
  51.  
  52. /* ----------------
  53.  *    variables and macros
  54.  * ----------------
  55.  */
  56. static LocalInvalid Invalid = EmptyLocalInvalid;    /* XXX global */
  57. static bool    RefreshWhenInvalidate = false;
  58.  
  59. ObjectId MyRelationRelationId =     InvalidObjectId;
  60. ObjectId MyAttributeRelationId = InvalidObjectId;
  61. ObjectId MyAMRelationId =     InvalidObjectId;
  62. ObjectId MyAMOPRelationId =     InvalidObjectId;
  63.  
  64. #define ValidateHacks() \
  65.     if (!ObjectIdIsValid(MyRelationRelationId)) getmyrelids()
  66.  
  67. /* ----------------------------------------------------------------
  68.  *        "local" invalidation support functions
  69.  * ----------------------------------------------------------------
  70.  */
  71.  
  72. /* --------------------------------
  73.  *    InvalidationEntryAllocate
  74.  * --------------------------------
  75.  */
  76. /**** xxref:
  77.  *           CacheIdRegisterLocalInvalid
  78.  *           RelationIdRegisterLocalInvalid
  79.  ****/
  80. InvalidationEntry
  81. InvalidationEntryAllocate(size)
  82.     uint16    size;
  83. {
  84.     InvalidationEntryData    *entryDataP;
  85.     entryDataP = (InvalidationEntryData *)
  86.     malloc(sizeof (char *) + size);    /* XXX alignment */
  87.     entryDataP->nextP = NULL;
  88.     return ((Pointer) &entryDataP->userData);
  89. }
  90.  
  91. /* --------------------------------
  92.  *    LocalInvalidRegister
  93.  * --------------------------------
  94.  */
  95. /**** xxref:
  96.  *           CacheIdRegisterLocalInvalid
  97.  *           RelationIdRegisterLocalInvalid
  98.  ****/
  99. LocalInvalid
  100. LocalInvalidRegister(invalid, entry)
  101.     LocalInvalid    invalid;
  102.     InvalidationEntry    entry;
  103. {
  104.     Assert(PointerIsValid(entry));
  105.     
  106.     ((InvalidationUserData *)entry)->dataP[-1] =
  107.     (InvalidationUserData *)invalid;
  108.     
  109.     return (entry);
  110. }
  111.  
  112. /* --------------------------------
  113.  *    LocalInvalidInvalidate
  114.  * --------------------------------
  115.  */
  116. /**** xxref:
  117.  *           RegisterInvalid
  118.  ****/
  119. void
  120. LocalInvalidInvalidate(invalid, function)
  121.     LocalInvalid    invalid;
  122.     void        (*function)();
  123. {
  124.     InvalidationEntryData    *entryDataP;
  125.     
  126.     while (PointerIsValid(invalid)) {
  127.     entryDataP = (InvalidationEntryData *)
  128.         &((InvalidationUserData *)invalid)->dataP[-1];
  129.     
  130.     if (PointerIsValid(function)) {
  131.         (*function)((Pointer) &entryDataP->userData);
  132.     }
  133.     
  134.     invalid = (Pointer) entryDataP->nextP;
  135.     
  136.     /* help catch errors */
  137.     entryDataP->nextP = (InvalidationUserData *) NULL;
  138.     
  139.     free((Pointer)entryDataP);
  140.     }
  141. }
  142.  
  143. /* ----------------------------------------------------------------
  144.  *              private support functions
  145.  * ----------------------------------------------------------------
  146.  */
  147. /* --------------------------------
  148.  *    CacheIdRegisterLocalInvalid
  149.  * --------------------------------
  150.  */
  151. #ifdef    INVALIDDEBUG
  152. #define CacheIdRegisterLocalInvalid_DEBUG1 \
  153.    elog(DEBUG, "CacheIdRegisterLocalInvalid(%d, %d, [%d, %d])", \
  154.     cacheId, hashIndex, ItemPointerGetBlockNumber(pointer), \
  155.     ItemPointerSimpleGetOffsetNumber(pointer))
  156. #else
  157. #define CacheIdRegisterLocalInvalid_DEBUG1
  158. #endif    INVALIDDEBUG
  159.  
  160. /**** xxref:
  161.  *           used as a pointer in RelationInvalidateHeapTuple
  162.  ****/
  163. static void
  164. CacheIdRegisterLocalInvalid(cacheId, hashIndex, pointer)
  165.     Index    cacheId;
  166.     Index    hashIndex;
  167.     ItemPointer    pointer;
  168. {
  169.     InvalidationMessage    message;
  170.     
  171.     /* ----------------
  172.      *    debugging stuff
  173.      * ----------------
  174.      */
  175.     CacheIdRegisterLocalInvalid_DEBUG1;
  176.     
  177.     /* ----------------
  178.      *    create a message describing the system catalog tuple
  179.      *  we wish to invalidate.
  180.      * ----------------
  181.      */
  182.     message = (InvalidationMessage)
  183.     InvalidationEntryAllocate(sizeof (InvalidationMessageData));
  184.     
  185.     message->kind = 'c';
  186.     message->any.catalog.cacheId = cacheId;
  187.     message->any.catalog.hashIndex = hashIndex;
  188.     
  189.     ItemPointerCopy(pointer, &message->any.catalog.pointerData);
  190.     
  191.     /* ----------------
  192.      *    Note: Invalid is a global variable
  193.      * ----------------
  194.      */
  195.     Invalid = LocalInvalidRegister(Invalid, (InvalidationEntry)message);
  196. }
  197.  
  198. /* --------------------------------
  199.  *    RelationIdRegisterLocalInvalid
  200.  * --------------------------------
  201.  */
  202. /**** xxref:
  203.  *           used as a pointer in RelationInvalidateHeapTuple
  204.  ****/
  205. static void
  206. RelationIdRegisterLocalInvalid(relationId, objectId)
  207.     ObjectId    relationId;
  208.     ObjectId    objectId;
  209. {
  210.     InvalidationMessage    message;
  211.     
  212.     /* ----------------
  213.      *    debugging stuff
  214.      * ----------------
  215.      */
  216. #ifdef    INVALIDDEBUG
  217.     elog(DEBUG, "RelationRegisterLocalInvalid(%d, %d)", relationId,
  218.      objectId);
  219. #endif    /* defined(INVALIDDEBUG) */
  220.     
  221.     /* ----------------
  222.      *    create a message describing the relation descriptor
  223.      *  we wish to invalidate.
  224.      * ----------------
  225.      */
  226.     message = (InvalidationMessage)
  227.     InvalidationEntryAllocate(sizeof (InvalidationMessageData));
  228.     
  229.     message->kind = 'r';
  230.     message->any.relation.relationId = relationId;
  231.     message->any.relation.objectId = objectId;
  232.     
  233.     /* ----------------
  234.      *    Note: Invalid is a global variable
  235.      * ----------------
  236.      */
  237.     Invalid = LocalInvalidRegister(Invalid, (InvalidationEntry)message);
  238. }
  239.  
  240. /* --------------------------------
  241.  *    getmyrelids
  242.  * --------------------------------
  243.  */
  244. void
  245. getmyrelids()
  246. {
  247.     HeapTuple    tuple;
  248.      
  249.     tuple = SearchSysCacheTuple(RELNAME, RelationRelationName);
  250.     Assert(HeapTupleIsValid(tuple));
  251.     MyRelationRelationId = tuple->t_oid;
  252.      
  253.     tuple = SearchSysCacheTuple(RELNAME, AttributeRelationName);
  254.     Assert(HeapTupleIsValid(tuple));
  255.     MyAttributeRelationId = tuple->t_oid;
  256.      
  257.     tuple = SearchSysCacheTuple(RELNAME, AccessMethodRelationName);
  258.     Assert(HeapTupleIsValid(tuple));
  259.     MyAMRelationId = tuple->t_oid;
  260.      
  261.     tuple = SearchSysCacheTuple(RELNAME, AccessMethodOperatorRelationName);
  262.     Assert(HeapTupleIsValid(tuple));
  263.     MyAMOPRelationId = tuple->t_oid;
  264. }
  265.  
  266. /* --------------------------------
  267.  *    CacheIdInvalidate
  268.  *
  269.  *    This routine can invalidate an tuple in a system catalog cache
  270.  *    or a cached relation descriptor.  You pay your money and you
  271.  *    take your chances...
  272.  * --------------------------------
  273.  */
  274. #ifdef    INVALIDDEBUG
  275. #define CacheIdInvalidate_DEBUG1 \
  276.    elog(DEBUG, "CacheIdInvalidate(%d, %d, 0x%x[%d])", cacheId, hashIndex,\
  277.     pointer, ItemPointerIsValid(pointer))
  278. #else
  279. #define CacheIdInvalidate_DEBUG1
  280. #endif    /* defined(INVALIDDEBUG) */
  281.  
  282. static void
  283. CacheIdInvalidate(cacheId, hashIndex, pointer)
  284.     Index    cacheId;
  285.     Index    hashIndex;
  286.     ItemPointer    pointer;
  287. {
  288.     InvalidationMessage    message;
  289.      
  290.     /* ----------------
  291.      *    assume that if the item pointer is valid, then we are
  292.      *  invalidating an item in the specified system catalog cache.
  293.      * ----------------
  294.      */
  295.     if (ItemPointerIsValid(pointer)) {
  296.     CatalogCacheIdInvalidate(cacheId, hashIndex, pointer);
  297.     return;
  298.     }
  299.     
  300.     CacheIdInvalidate_DEBUG1;
  301.     
  302.     ValidateHacks();    /* XXX */
  303.      
  304.     /* ----------------
  305.      *    if the cacheId is the oid of any of the tuples in the
  306.      *  following system relations, then assume we are invalidating
  307.      *  a relation descriptor
  308.      * ----------------
  309.      */
  310.     if (cacheId == MyRelationRelationId) {
  311.     RelationIdInvalidateRelationCacheByRelationId(hashIndex);
  312.     return;
  313.     }
  314.     
  315.     if (cacheId == MyAttributeRelationId) {
  316.     RelationIdInvalidateRelationCacheByRelationId(hashIndex);
  317.     return;
  318.     }
  319.      
  320.     if (cacheId == MyAMRelationId) {
  321.     RelationIdInvalidateRelationCacheByAccessMethodId(hashIndex);
  322.     return;
  323.     }
  324.     
  325.     if (cacheId == MyAMOPRelationId) {
  326.     RelationIdInvalidateRelationCacheByAccessMethodId(InvalidObjectId);
  327.     return;
  328.     }
  329.      
  330.     /* ----------------
  331.      *    Yow! the caller asked us to invalidate something else.
  332.      * ----------------
  333.      */
  334.     elog(FATAL, "CacheIdInvalidate: cacheId=%d relation id?", cacheId);
  335. }
  336.  
  337. /* --------------------------------
  338.  *    ResetSystemCaches
  339.  *
  340.  *    this blows away all tuples in the system catalog caches and
  341.  *    all the cached relation descriptors (and closes the files too).
  342.  * --------------------------------
  343.  */
  344. static void
  345. ResetSystemCaches()
  346. {
  347.     ResetSystemCache();
  348.     RelationCacheInvalidate(false); 
  349. }
  350.  
  351. /* --------------------------------
  352.  *    InvalidationMessageRegisterSharedInvalid
  353.  * --------------------------------
  354.  */
  355. #ifdef    INVALIDDEBUG
  356. #define InvalidationMessageRegisterSharedInvalid_DEBUG1 \
  357.    elog(DEBUG,\
  358.     "InvalidationMessageRegisterSharedInvalid(c, %d, %d, [%d, %d])",\
  359.     message->any.catalog.cacheId,\
  360.     message->any.catalog.hashIndex,\
  361.     ItemPointerGetBlockNumber(&message->any.catalog.pointerData),\
  362.     ItemPointerSimpleGetOffsetNumber(&message->any.catalog.pointerData))
  363. #define InvalidationMessageRegisterSharedInvalid_DEBUG2 \
  364.     elog(DEBUG, \
  365.      "InvalidationMessageRegisterSharedInvalid(r, %d, %d)", \
  366.      message->any.relation.relationId, \
  367.      message->any.relation.objectId)
  368. #else    
  369. #define InvalidationMessageRegisterSharedInvalid_DEBUG1
  370. #define InvalidationMessageRegisterSharedInvalid_DEBUG2
  371. #endif INVALIDDEBUG
  372.  
  373. /**** xxref:
  374.  *           used as a pointer in RegisterInvalid
  375.  ****/
  376. static void
  377. InvalidationMessageRegisterSharedInvalid(message)
  378.     InvalidationMessage    message;
  379. {
  380.     Assert(PointerIsValid(message));
  381.     
  382.     switch (message->kind) {
  383.     case 'c':    /* cached system catalog tuple */
  384.     InvalidationMessageRegisterSharedInvalid_DEBUG1;
  385.     
  386.     RegisterSharedInvalid(message->any.catalog.cacheId,
  387.                   message->any.catalog.hashIndex,
  388.                   &message->any.catalog.pointerData);
  389.     break;
  390.     
  391.     case 'r':   /* cached relation descriptor */
  392.     InvalidationMessageRegisterSharedInvalid_DEBUG2;
  393.      
  394.     RegisterSharedInvalid(message->any.relation.relationId,
  395.                   message->any.relation.objectId,
  396.                   (ItemPointer) NULL);
  397.     break;
  398.     
  399.     default:
  400.     elog(FATAL,
  401.          "InvalidationMessageRegisterSharedInvalid: `%c' kind",
  402.          message->kind);
  403.     }
  404. }
  405.  
  406. /* --------------------------------
  407.  *    InvalidationMessageCacheInvalidate
  408.  * --------------------------------
  409.  */
  410. #ifdef    INVALIDDEBUG
  411. #define InvalidationMessageCacheInvalidate_DEBUG1 \
  412.    elog(DEBUG, "InvalidationMessageCacheInvalidate(c, %d, %d, [%d, %d])",\
  413.     message->any.catalog.cacheId,\
  414.     message->any.catalog.hashIndex,\
  415.     ItemPointerGetBlockNumber(&message->any.catalog.pointerData),\
  416.     ItemPointerSimpleGetOffsetNumber(&message->any.catalog.pointerData))
  417. #define InvalidationMessageCacheInvalidate_DEBUG2 \
  418.    elog(DEBUG, "InvalidationMessageCacheInvalidate(r, %d, %d)", \
  419.     message->any.relation.relationId, \
  420.     message->any.relation.objectId)
  421. #else
  422. #define InvalidationMessageCacheInvalidate_DEBUG1
  423. #define InvalidationMessageCacheInvalidate_DEBUG2
  424. #endif    /* defined(INVALIDDEBUG) */
  425.  
  426. /**** xxref:
  427.  *           used as a pointer in RegisterInvalid
  428.  ****/
  429. static void
  430. InvalidationMessageCacheInvalidate(message)
  431.     InvalidationMessage    message;
  432. {
  433.     Assert(PointerIsValid(message));
  434.      
  435.     switch (message->kind) {
  436.     case 'c':  /* cached system catalog tuple */
  437.     InvalidationMessageCacheInvalidate_DEBUG1;
  438.     
  439.     CatalogCacheIdInvalidate(message->any.catalog.cacheId,
  440.                  message->any.catalog.hashIndex,
  441.                  &message->any.catalog.pointerData);
  442.     break;
  443.     
  444.     case 'r':  /* cached relation descriptor */
  445.     InvalidationMessageCacheInvalidate_DEBUG2;
  446.     
  447.     /* XXX ignore this--is this correct ??? */
  448.     break;
  449.     
  450.     default:
  451.     elog(FATAL, "InvalidationMessageCacheInvalidate: `%c' kind",
  452.          message->kind);
  453.     }
  454. }
  455.  
  456. /* --------------------------------
  457.  *    RelationInvalidateRelationCache
  458.  * --------------------------------
  459.  */
  460. /**** xxref:
  461.  *           RelationInvalidateHeapTuple
  462.  ****/
  463. static void
  464. RelationInvalidateRelationCache(relation, tuple, function)
  465.     Relation    relation;
  466.     HeapTuple    tuple;
  467.     void    (*function)();
  468. {
  469.     ObjectId    relationId;
  470.     ObjectId    objectId;
  471.      
  472.     /* ----------------
  473.      *    get the relation object id
  474.      * ----------------
  475.      */
  476.     ValidateHacks();    /* XXX */
  477.     relationId = RelationGetRelationId(relation);
  478.      
  479.     /* ----------------
  480.      *    
  481.      * ----------------
  482.      */
  483.     if (relationId == MyRelationRelationId) {
  484.     objectId = tuple->t_oid;
  485.     } else if (relationId == MyAttributeRelationId) {
  486.     objectId = ((AttributeTupleForm)GETSTRUCT(tuple))->attrelid;
  487.     } else if (relationId == MyAMRelationId) {
  488.     objectId = tuple->t_oid;
  489.     } else if (relationId == MyAMOPRelationId) {
  490.     ; /* objectId is unused */
  491.     } else 
  492.     return;
  493.      
  494.     /* ----------------
  495.      *      can't handle immediate relation descriptor invalidation
  496.      * ----------------
  497.      */
  498.     Assert(PointerIsValid(function));
  499.      
  500.     (*function)(relationId, objectId);
  501. }
  502.  
  503. /* --------------------------------
  504.  *    DiscardInvalid
  505.  * --------------------------------
  506.  */
  507. void
  508. DiscardInvalid()
  509. {
  510.     /* ----------------
  511.      *    debugging stuff
  512.      * ----------------
  513.      */
  514. #ifdef    INVALIDDEBUG
  515.     elog(DEBUG, "DiscardInvalid called");
  516. #endif    /* defined(INVALIDDEBUG) */
  517.      
  518.     InvalidateSharedInvalid(CacheIdInvalidate, ResetSystemCaches);
  519. }
  520.  
  521. /* --------------------------------
  522.  *    RegisterInvalid
  523.  * --------------------------------
  524.  */
  525. void
  526. RegisterInvalid(send)
  527.     bool    send;
  528. {
  529.     /* ----------------
  530.      *    debugging stuff
  531.      * ----------------
  532.      */
  533. #ifdef    INVALIDDEBUG
  534.     elog(DEBUG, "RegisterInvalid(%d) called", send);
  535. #endif    /* defined(INVALIDDEBUG) */
  536.      
  537.     /* ----------------
  538.      *    Note: Invalid is a global variable
  539.      * ----------------
  540.      */
  541.     if (send)
  542.     LocalInvalidInvalidate(Invalid,
  543.                    InvalidationMessageRegisterSharedInvalid);
  544.     else
  545.     LocalInvalidInvalidate(Invalid,
  546.                    InvalidationMessageCacheInvalidate);
  547.     
  548.     Invalid = EmptyLocalInvalid;
  549. }
  550.  
  551. /* --------------------------------
  552.  *    SetRefreshWhenInvalidate
  553.  * --------------------------------
  554.  */
  555. void
  556. SetRefreshWhenInvalidate(on)
  557.     bool    on;
  558. {
  559. #ifdef    INVALIDDEBUG
  560.     elog(DEBUG, "RefreshWhenInvalidate(%d) called", on);
  561. #endif    /* defined(INVALIDDEBUG) */
  562.     
  563.     RefreshWhenInvalidate = on;
  564. }
  565.  
  566. /* --------------------------------
  567.  *    RelationInvalidateHeapTuple
  568.  * --------------------------------
  569.  */
  570. #ifdef    INVALIDDEBUG
  571. #define RelationInvalidateHeapTuple_DEBUG1 \
  572.     elog(DEBUG, "RelationInvalidateHeapTuple(%.16s, [%d,%d])", \
  573.      RelationGetRelationName(relation), \
  574.      ItemPointerGetBlockNumber(&tuple->t_ctid), \
  575.      ItemPointerSimpleGetOffsetNumber(&tuple->t_ctid))
  576. #else
  577. #define RelationInvalidateHeapTuple_DEBUG1
  578. #endif    /* defined(INVALIDDEBUG) */
  579.  
  580. void
  581. RelationInvalidateHeapTuple(relation, tuple)
  582.     Relation    relation;
  583.     HeapTuple    tuple;
  584. {
  585.     /* ----------------
  586.      *    sanity checks
  587.      * ----------------
  588.      */
  589.     Assert(RelationIsValid(relation));
  590.     Assert(HeapTupleIsValid(tuple));
  591.  
  592.     if (IsBootstrapProcessingMode())
  593.     return;
  594.     /* ----------------
  595.      *    this only works for system relations now
  596.      * ----------------
  597.      */
  598.     if (! issystem(&RelationGetRelationTupleForm(relation)->relname))
  599.     return;
  600.      
  601.     /* ----------------
  602.      *    debugging stuff
  603.      * ----------------
  604.      */
  605.     RelationInvalidateHeapTuple_DEBUG1;
  606.      
  607.     /* ----------------
  608.      *    
  609.      * ----------------
  610.      */
  611.     RelationInvalidateCatalogCacheTuple(relation,
  612.                     tuple,
  613.                     CacheIdRegisterLocalInvalid);
  614.      
  615.     RelationInvalidateRelationCache(relation,
  616.                     tuple,
  617.                     RelationIdRegisterLocalInvalid);
  618.         
  619.     if (RefreshWhenInvalidate)
  620.     RelationInvalidateCatalogCacheTuple(relation,
  621.                         tuple,
  622.                         (void (*)()) NULL);
  623. }
  624.  
  625.